/*
 * Created by SharpDevelop.
 * User: Vivek
 * Date: 9/7/2009
 * Time: 12:21 PM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Collections.Generic;
using System.IO;
namespace GxcToCsharpParser.GrcParser
{
   /// <summary>
   /// Description of GrcParser.
   /// </summary>
   public class GrcParser
   {
      public List<IResource> Resources { get; set; }
      public bool IsComplexGrcFile { get; set; }
      private FormResource formResource;
      private ListResource listResource;
      private HelpResource helpResource;
      bool isReadingForm;
      bool isReadingList;
      bool isReadingHelp;
      public int NumberOfForms { get; set; }
      public bool HasCompiled { get; set; }
      public GrcParser()
      {
         NumberOfForms = 0;
         HasCompiled = true;
      }

      public void ParseFile(string grcFile)
      {
         if (File.Exists(grcFile))
         {
            using (StreamReader reader = new StreamReader(grcFile))
            {
               Resources = new List<IResource>();
               while (reader.EndOfStream == false)
               {
                  string line = reader.ReadLine().Trim();
                  int comment = line.IndexOf("//");
                  if (comment != -1)
                     line = line.Remove(comment);
                  if (line.Length > 0)
                  {
                     string[] tokens =GetGrcLineTokens(line);
                     bool foundWidget = false;
                     string widget = "";
                     List<string> args = new List<string>();
                     foreach (string token in tokens)
                     {
                        if (token.ToUpper() == "RESOURCE")
                        {
                           AddResourceReadSoFar();
                           continue;
                        }
                        if (foundWidget == false)
                        {
                           widget = token.ToUpper();
                           foundWidget = true;
                        }
                        else
                        {
                           args.Add(token);
                        }



                     }
                     try
                     {
                        ParseWidget(widget, args);
                     }
                     catch (Exception e)
                     {
                        Console.WriteLine("Line "+line);
                        Console.WriteLine(e.Message);
                        Console.WriteLine(e.StackTrace);
                        HasCompiled = false;

                     }
                  }
               }
            }
         }
         if (isReadingHelp)
            Resources.Add(helpResource);
         if (NumberOfForms > 1)
            IsComplexGrcFile = true;
         
      }

      private string[] GetGrcLineTokens(string line)
      {
         bool inString = false;
         List<string> tokens = new List<string>();
         int start = 0;
         int end = 0;
         foreach (char ch in line)
         {
            if (ch == '\"')
               inString = !inString;
            else if(ch == ','&& !inString)
            {
               tokens.Add(line.Substring(start,end-start).Trim());
               start = end+1;
               
            }
            end++;

         }
         tokens.Add(line.Substring(start).Trim());
         return tokens.ToArray();
      }

      private void AddResourceReadSoFar()
      {
         if (isReadingForm)
            Resources.Add(formResource);
         else if (isReadingList)
         {
            if (listResource.Items.Count == 0)
               listResource.IsDynamic = true;
            Resources.Add(listResource);
         }
         else if (isReadingForm)
            Resources.Add(helpResource);
      }
      private void ParseWidget(string widget, List<string> arguments)
      {
         switch (widget)
         {
            case "FORM":
               ParseForm(arguments);
               IsReadingForm();
               break;
            case "LIST":
               ParseList(arguments);
               IsReadingList();
               break;
            case "HELP":
               ParseHelp(arguments);
               IsReadingHelp();
               break;
            case "EDIT":
               ParseEdit(arguments);
               break;
            case "FEDIT":
               ParseFolderEdit(arguments);
               break;
            case "LEDIT":
               ParseListEdit(arguments);
               break;
            case "CEDIT":
               ParseColorEdit(arguments);
               break;
            case "EBUT":
               ParseButton(arguments);
               break;
            case "HBUT":
               ParseHelpButton(arguments);
               break;
            case "ITEM":
               ParseListItem(arguments);
               break;
            default:
               UnableToParseWidget(widget, arguments);
               break;


         }
      }

      private void IsReadingHelp()
      {
         isReadingHelp = true;
         isReadingForm = isReadingList = false;
      }

      private void IsReadingList()
      {
         isReadingList = true;
         isReadingForm = isReadingHelp = false;
      }

      private void IsReadingForm()
      {
         isReadingForm = true;
         isReadingList = isReadingHelp = false;
         NumberOfForms++;
      }
      private void ParseForm(List<string> arguments)
      {
         formResource = new FormResource() { Name = arguments[0], Title = arguments[1], EscapeValue = int.Parse(arguments[2]) };
      }
      private void ParseList(List<string> arguments)
      {
         listResource = new ListResource() { Name = arguments[0] };
      }
      private void ParseHelp(List<string> arguments)
      {
         helpResource = new HelpResource() { Name = arguments[0], HelpFileName = arguments[1] };

      }
      private void ParseEdit(List<string> arguments)
      {
         EditWidget edit = new EditWidget(){Width=int.Parse(arguments[2]), Label=arguments[3]};
         if(arguments.Count>4)
            edit.Requried=arguments[4];
         if (arguments.Count > 5)
            edit.Validation = arguments[5];
         if(arguments.Count>6)
            edit.DefaultValue = arguments[6];
         formResource.Widgets.Add(edit);
      }
      private void ParseFolderEdit(List<string> arguments)
      {
         FolderEditWidget edit = new FolderEditWidget() { Width = int.Parse(arguments[2]), Label = arguments[3] };
         if (arguments.Count >4)
            edit.Requried = arguments[4];
         if (arguments.Count > 5)
            edit.Validation = arguments[5];
         if (arguments.Count > 6)
            edit.DefaultValue = arguments[6];
         if (arguments.Count > 7)
            edit.FilePath = arguments[7];
         if (arguments.Count > 8)
            edit.FileMask=arguments[8];

         formResource.Widgets.Add(edit);
      }
      private void ParseListEdit(List<string> arguments)
      {
         ListEditWidget edit = new ListEditWidget() { Width = int.Parse(arguments[2]), Label = arguments[3]};
         if (arguments.Count > 4)
            edit.Requried = arguments[4];
         if (arguments.Count > 5)
            edit.Validation = arguments[5];
         if (arguments.Count > 6)
            edit.DefaultValue = arguments[6];
         if (arguments.Count > 7)
            edit.ListResourceName = arguments[7];

         formResource.Widgets.Add(edit);
      }
      private void ParseColorEdit(List<string> arguments)
      {
         
         ColorEditWidget edit = new ColorEditWidget() { Width = int.Parse(arguments[2]), Label = arguments[3]}; ;
         if (arguments.Count > 4)
            edit.Requried = arguments[4];
         if (arguments.Count >5)
            edit.DefaultValue = arguments[5];
         formResource.Widgets.Add(edit); 
      }
      private void ParseButton(List<string> arguments)
      {
         ButtonWidget button = new ButtonWidget() { Label = arguments[0], ReturnValue = int.Parse(arguments[1]) };
         if (arguments.Count > 2 && arguments[2].ToUpper() == "CANCEL")
            button.IsCancelButton = true;
         formResource.Widgets.Add(button);
      }
      private void ParseHelpButton(List<string> arguments)
      {
         HelpButtonWidget helpButton = new HelpButtonWidget() { Label = arguments[0], HelpResource = arguments[1] };
      }
      private void ParseListItem(List<string> arguments)
      {
         ListItem item = null;
         if (arguments.Count == 1)
         {
            item =new ListItem() { Name = arguments[0], Alias = arguments[0] };
         }
         else
         {
             
            item = new ListItem() { Name = arguments[0], Alias = arguments[1] };
            
         }
         listResource.Items.Add(item);
      }

      private void UnableToParseWidget(string widget, List<string> arguments)
      {
         System.Diagnostics.Trace.TraceError("Unable to parse {0}", widget);
      }
   }
}
